test: add Vitest unit tests and Playwright E2E with MinIO S3 mock#20
Conversation
Add a Playwright E2E preparation flow that starts the test Postgres container, applies Prisma migrations, and seeds dummy CMS data before tests. Update CI to run the E2E job with the same docker-compose based flow, and document the test commands in README.md.
Commit 534f216 renamed `PAYLOAD_S3_TARGET_BUCKET` -> `S3_BUCKET` and removed `PAYLOAD_S3_BASE_URL` across source, but tests added afterward on this branch still referenced the old names, causing 4 failures in `s3.test.ts` and `public-url.test.ts`. - Rename `PAYLOAD_S3_TARGET_BUCKET` -> `S3_BUCKET` stubs in `s3.test.ts` and `public-url.test.ts` so module-time env reads actually pick up the custom bucket and region. - Drop the two `PAYLOAD_S3_BASE_URL` tests; that env var was deliberately deleted (not renamed) and re-introducing it would contradict the refactor. Add a symmetric negative case against `S3_BUCKET` instead. - Rename `PAYLOAD_S3_TARGET_BUCKET` -> `S3_BUCKET` in `src/tests/setup.ts` and `playwright.config.ts` so Vitest global setup and the Playwright web server actually propagate the bucket name to runtime code.
기존 `pnpm test:e2e`는 `cp .env.example .env`가 무조건 실행돼 개발자의 로컬 `.env`를 placeholder(`postgres://user:password@host:5432/schema`)로 덮어썼고, 그 결과 migrate/seed가 존재하지 않는 DB로 붙으려 실패하고 있었습니다. 이 커밋은 e2e 파이프라인 전체를 재정비합니다. - `.env.test` 도입 (dummy 값만 담겨있어 커밋). Playwright, prepare, seed 스크립트 모두 이 파일만 명시적으로 로드하므로 개발자 로컬 `.env`를 건드리지 않습니다. `.gitignore`에 `!.env.test` 예외 추가. - `playwright.config.ts`의 webServer `env:` 블록 제거 — Playwright가 자동으로 `process.env`를 상속하므로 중복. - `package.json`의 `test:e2e`, `test:e2e:ui`에서 `cp .env.example .env` 제거. - `docker-compose.test.yml`에 MinIO 서비스 추가. entrypoint를 override해 `mkdir -p /data/stdev-kr && exec minio server /data`로 버킷 디렉토리를 먼저 만든 뒤 서버를 기동 — 별도 init 사이드카 없이 한 서비스로 해결. - `src/utils/s3.ts`: AWS SDK 공식 env var인 `AWS_ENDPOINT_URL_S3`가 세팅되면 `endpoint + forcePathStyle: true`를 `S3Client`에 주입. 프로덕션에는 이 변수를 세팅하지 않으므로 동작 변화 없음. `.env.test`에 `AWS_ENDPOINT_URL_S3=http://127.0.0.1:9000` 포함. - `scripts/` → `src/scripts/`로 이동 (git rename으로 이력 보존). `src/utils/`(런타임 헬퍼)와 혼동되지 않도록 `src/tests/`, `src/e2e/` 와 평행한 형제 디렉토리로 배치. - `package.json`의 stale `migrate:payload` 엔트리 제거 — 참조하던 파일 `scripts/migrate-payload-to-prisma.ts`는 이미 커밋 534f216에서 PayloadCMS 정리와 함께 삭제됨. - `codecov.yml`의 ignore 경로를 `src/scripts/**/*`로 갱신. - `src/scripts/prepare-playwright-e2e.mjs`: 커스텀 pg_isready 폴링 루프 제거, `docker compose up -d --wait`로 postgres와 minio 둘 다 healthcheck 기반 대기. - README의 E2E 섹션에 MinIO 의존성 문구 추가.
|
@codex review |
직전 커밋 53c7767에서 `scripts/` → `src/scripts/`로 이동하면서 Vitest의
`coverage.include: ['src/**/*.{ts,tsx}']` glob이 `src/scripts/seed-playwright-e2e.ts`
(166 lines, 0% coverage)를 새로 포획해 전체 커버리지가 93.63%로 떨어졌습니다.
`codecov.yml`의 ignore 경로는 이동과 함께 갱신됐으나 `vitest.config.ts`의
exclude는 동기화되지 않은 상태였습니다.
- `vitest.config.ts`의 `coverage.exclude`에 `src/scripts/**` 추가 —
codecov.yml과 동기화. 운영 스크립트를 단위 테스트 95%로 요구하는 것은
합리적이지 않고, 실제 동작은 e2e의 `e2e:prepare`에서 검증됨.
- 같은 맥락으로 타입 전용 파일 `src/utils/cms-types.ts`도 exclude — v8
provider가 0/0 라인으로 잡아 리포트 노이즈였음.
- `src/utils/s3.test.ts`에 `AWS_ENDPOINT_URL_S3`가 세팅됐을 때의 업로드
경로를 커버하는 테스트 추가 — 53c7767에서 내가 추가한 MinIO endpoint
분기를 명시적으로 검증.
- `.github/workflows/ci.yml`의 build/test/e2e 3개 job에서 `cp .env.example .env`
제거 — 53c7767에서 `package.json`의 동일 명령은 제거했으나 CI workflow
에는 잔존했음. test 잡은 `src/tests/setup.ts`, e2e 잡은 `.env.test`가
env를 담당하므로 모두 안전.
결과: lines 99.43% / branches 97.47% / functions 99.25% / statements 99.43%.
모든 threshold(95/90/95/95) 통과. Vitest 692 tests pass.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 53c77676bf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const adapter = new PrismaPg({ | ||
| connectionString: withDatabaseSslParams(databaseUrl), | ||
| }) |
There was a problem hiding this comment.
Pass computed SSL settings into PrismaPg adapter
DATABASE_SSL_REJECT_UNAUTHORIZED and the local-host detection are computed here, but the resulting ssl object is never passed to new PrismaPg(...). That means this new configuration path is a no-op, so deployments that rely on DATABASE_SSL_REJECT_UNAUTHORIZED=false (for self-signed/internal certs) will still use the adapter default TLS behavior and can fail to connect.
Useful? React with 👍 / 👎.
| data: { | ||
| id: userId, | ||
| name: 'Test Admin', | ||
| email: 'e2e@stdev.kr', |
There was a problem hiding this comment.
Generate unique seeded admin email for retried E2E runs
This seed helper always inserts email: 'e2e@stdev.kr', but User.email is unique and CI enables Playwright retries. If the CRUD test fails after creating this user, a retry will attempt the same insert without cleanup and fail with a unique-constraint error before exercising the scenario, turning retries into deterministic false failures.
Useful? React with 👍 / 👎.
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment Thanks for integrating Codecov - We've got you covered ☂️ |
직전 커밋 cb0b41d에서 build/test/e2e 3개 job의 `cp .env.example .env`를 모두 제거했으나, `pnpm build`의 Next.js page collection 단계가 `@/utils/prisma`의 `DATABASE_URL is required` 가드를 터뜨려 build와 e2e가 실패했습니다(test job은 `src/tests/setup.ts`가 env를 세팅해 영향 없음). `.env.example`의 placeholder 대신 **`.env.test`의 실제 테스트 값**을 복사하도록 복구: - `build` job: `pnpm install` 직후 `cp .env.test .env` 스텝 추가. - `e2e` job: `pnpm test:e2e:install` 직후 `cp .env.test .env` 스텝 추가. `pnpm test:e2e`가 내부적으로 `pnpm build`를 실행하므로 build와 동일한 이유로 필요. - `test` job은 그대로 유지 — Vitest는 `.env`를 자동 로드하지 않고 `src/tests/setup.ts`에서 env를 주입하므로 cp 불필요. `.env.test`는 e2e용 dummy 값이라 build에 해가 없고, `.env.example`의 placeholder보다 실제 동작 환경에 가까워 의도도 더 선명합니다.
배경
현재 레포에는 자동화 테스트가 없어 리팩토링이나 기능 추가 시 회귀를 잡기 어려웠습니다. 이 PR은 세 레이어의 테스트 인프라를 추가합니다.
codecov.yml)변경 사항
Vitest 테스트 스위트 (
75da9e9)src/utils/*전체, 주요 컴포넌트,(stdev)페이지들,(cms)/admin액션, Prisma/better-auth 통합aws-sdk-client-mock으로 모킹, 파일 업로드는node:buffer의File폴리필로 실제 바이트 검증Playwright E2E (
995f778, 이 PR 후반부에서 추가 정비)admin-signin,admin-crud-smoke,public-navigation,public-responsivedocker-compose.test.yml의 격리된 Postgres에 Prisma migration + seed 후 실행src/e2e/fixtures/{db,auth}.ts에 DB 상태 관리 + better-auth 세션 헬퍼초기 구성 이슈 정리 (
8e80305)커밋
534f216의 PayloadCMS 정리에서 이미 이름이 바뀐 env var(PAYLOAD_S3_TARGET_BUCKET→S3_BUCKET)과 삭제된 env var(PAYLOAD_S3_BASE_URL)을 참조하던 stale 테스트 4건을 현재 컨벤션으로 정합.E2E 파이프라인 재정비 (
53c7767)문제: 기존
pnpm test:e2e는cp .env.example .env를 무조건 실행해 개발자 로컬.env를postgres://user:password@host:5432/schemaplaceholder로 덮어썼고, 그 결과 Prisma migration이 존재하지 않는 DB에 붙으려다 실패했습니다. 사실상 작동하지 않는 상태였습니다.해결:
.env.test도입: e2e 전용 env를 dummy 값으로 커밋. Playwright/prepare/seed 스크립트 모두 이 파일만 명시적으로 로드 → 개발자 로컬.env를 건드리지 않음.playwright.config.ts의 webServerenv:블록은 중복이므로 제거 (Playwright가 자동으로process.env를 상속).docker-compose.test.yml에 MinIO 사이드카 추가. entrypoint 오버라이드로mkdir -p /data/stdev-kr && exec minio server /data한 줄로 버킷 초기화(별도 init 사이드카 없음).src/utils/s3.ts에 AWS SDK 공식 env varAWS_ENDPOINT_URL_S3핸들링 추가 (+forcePathStyle: true). 프로덕션은 이 변수가 없으므로 동작 변화 없음.scripts/→src/scripts/로 이동 (git rename으로 이력 보존).src/utils/(런타임 헬퍼)와 혼동되지 않도록src/tests/,src/e2e/와 평행한 형제 디렉토리 구조.prepare-playwright-e2e.mjs: 커스텀pg_isready폴링 루프 제거,docker compose up -d --wait로 postgres + minio healthcheck 기반 대기.부가 정리
package.json의 stalemigrate:payload스크립트 삭제 — 참조 파일(scripts/migrate-payload-to-prisma.ts)은534f216에서 이미 삭제됨.README.md의 E2E 섹션에 MinIO 의존성 명시.codecov.yml의 coverage ignore 경로 갱신 (scripts/**/*→src/scripts/**/*).검증
pnpm test: 51 files / 691 tests PASSpnpm lint: cleanpnpm e2e:prepare: 전체 파이프라인(compose up → migrate → seed) 실환경에서 성공 확인@aws-sdk/client-s3로 PUT/GET/LIST 왕복 성공실행 방법
```bash
pnpm install
pnpm test # 단위/컴포넌트
pnpm test:coverage # 커버리지
pnpm test:e2e:install # 최초 1회, Chromium 설치
pnpm test:e2e # E2E (Docker 필요)
```
참고
dotenv는 override 기본값이 false라 CI가 export한 secret이.env.test값보다 우선합니다 (결정성 + 유연성).tmpfs: /data로 데이터를 저장하지 않아 테스트 간 격리가 자동 보장됩니다.